#include "actionimage.h"
#include "actionfiltre.h"
#include "ui_fenetreimage.h"

ActionImage::ActionImage(QWidget * mw) :
    QWidget(mw)
{
    mainWindow  = (MainWindow *)mw;
}

ActionImage::~ActionImage()
{

}

void ActionImage::connect(Ui::MainWindow* ui)
{
    QObject::connect(ui->actionFusionner, SIGNAL(triggered()), this, SLOT(fusionAvecUneAutreImage()));
    QObject::connect(ui->actionCrop, SIGNAL(triggered()), this, SLOT(crop()));
    QObject::connect(ui->actionDecouper, SIGNAL(triggered()), this, SLOT(crop()));

    QObject::connect(ui->actionScale, SIGNAL(triggered()), this, SLOT(redimensionnement()));
    QObject::connect(ui->actionSeam_carving, SIGNAL(triggered()), this, SLOT(seamCarving()));
    QObject::connect(ui->actionSeam_carving_previsualisation, SIGNAL(triggered()), this, SLOT(seamCarvingPrevisualisation()));

    QObject::connect(ui->actionSelection_Rectangulaire, SIGNAL(triggered()),this,SLOT(selectionRectangulaire()));
    QObject::connect(ui->actionPipette,SIGNAL(triggered()),this,SLOT(pipette()));
    QObject::connect(ui->actionCrayon, SIGNAL(triggered()), this, SLOT(crayon()));
    QObject::connect(ui->actionDeplacement, SIGNAL(triggered()), this, SLOT(deplacement()));
    QObject::connect(ui->actionAccentuation_de_contours, SIGNAL(triggered()), this, SLOT(accentuationContours()));

    QObject::connect(ui->actionCiseaux, SIGNAL(triggered()), this, SLOT(ciseaux()));
    QObject::connect(ui->actionDecoupage_intelligent, SIGNAL(triggered()), this, SLOT(autocrop()));
}


void ActionImage::relacheOutils(){
    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    // on remet le curseur par defaut
    this->fenetre->getMonUi()->VueImage->setCursor(Qt::ArrowCursor);

    //on relache les boutons
    this->mainWindow->getUi()->actionCrop->setChecked(false);
    this->mainWindow->getUi()->actionPipette->setChecked(false);
    this->mainWindow->getUi()->actionSelection_Rectangulaire->setChecked(false);
    this->mainWindow->getUi()->actionCrayon->setChecked(false);
    this->mainWindow->getUi()->actionDeplacement->setChecked(false);
    this->mainWindow->getUi()->actionCiseaux->setChecked(false);

}

void ActionImage::setOutilsAccessibles(bool accessible){
    this->mainWindow->getUi()->actionCrop->setCheckable(accessible);
    this->mainWindow->getUi()->actionPipette->setCheckable(accessible);
    this->mainWindow->getUi()->actionSelection_Rectangulaire->setCheckable(accessible);
    this->mainWindow->getUi()->actionCrayon->setCheckable(accessible);
    this->mainWindow->getUi()->actionDeplacement->setCheckable(accessible);
    this->mainWindow->getUi()->actionCiseaux->setCheckable(accessible);
}

FenetreImage * ActionImage::getFenetreImageCourante(){
    QMdiSubWindow * sousFenetre   = mainWindow->getMdiArea()->activeSubWindow();
    if(sousFenetre == NULL){ return NULL; }

    return (FenetreImage *)(sousFenetre->widget());
}


/*********SLOT*********/

void ActionImage::fusionAvecUneAutreImage(){
    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }


    Calque *copie = fenetre->getCalqueCourant()->copie();

     ElementHistorique* eh = new ElementHistorique(QString("fusion"), copie);
     fenetre->historique.ajouter(eh);

    // on demande quelle image on veut fusionner avec la courante
    // a l'aide d'une boite de dialogue
    QString* selectedImage = new QString;
    *selectedImage = QFileDialog::getOpenFileName(this, "Ouvrir une image", QString(), "Images (*.png *pnm *.gif *.jpg *.jpeg *.bmp)");

    if(selectedImage->isEmpty()){
        return;
    }
    //si l utilisateur a selectionne une image on la charge
    Calque* image = new Calque();
    image->load(*selectedImage);
    image->setNom("Fusion");

    // ensuite, il faut connaitre la transparence
    // on la demande

    //Calque * base  = fenetre->getCalqueCourant();

    //MonDialogueTransparence * monDialogue = new MonDialogueTransparence(base, image, this);
    //int acceptation = monDialogue->exec();

    //if(acceptation == QDialog::Accepted){
        //int resultat    = monDialogue->getValeurRetour();

        // a la validation, on fabrique cette nouvelle image
        //Calque * imgVide= new Calque(image->width(), image->height(), QImage::Format_ARGB32);
        //QPainter painter(imgVide);
        //qreal opacite   = resultat/100.0;
        //painter.setOpacity(opacite);
        //painter.drawImage(0,0,*image);
        //painter.end();

        // on l'ajoute a la fenetre active
        fenetre->ajouterCalque(image);

        //fenetre->getMonEcouteur()->setMode(EcouteurSourisGraphicsView::FUSION);
    //}

    //suppression
    //    delete imageVide;
        delete selectedImage;
    //    delete monDialogue;
}

void ActionImage::crop(){
    relacheOutils();

    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    this->fenetre->getMonUi()->VueImage->setCursor(Qt::CrossCursor);
    this->mainWindow->getUi()->actionCrop->setChecked(true);

    fenetre->getMonEcouteur()->setMode(EcouteurSourisGraphicsView::CROP);
}

void ActionImage::redimensionnement(){
    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    Calque * image  = fenetre->getCalqueCourant();

    // on garde en memoire l'ancienne image
    Calque *memoire = fenetre->getCalqueCourant()->copie();
    ElementHistorique* eh = new ElementHistorique(QString("redimensionnement"), memoire);
    fenetre->historique.ajouter(eh);

    MonDialogueRedimensionnement * monDialogue = new MonDialogueRedimensionnement(this);
    int acceptation = monDialogue->exec();

    if(acceptation == QDialog::Accepted){

        // on calcule les nouvelles dimensions
        int largeur = (image->width()*monDialogue->getPourcentageLargeur()) /100;
        int hauteur = (image->height()*monDialogue->getPourcentageHauteur()) /100;

        // la difference de taille
        int nbPixelsEnPlusEnX   = largeur - image->width();
        int nbPixelsEnPlusEnY   = hauteur - image->height();

        // la taille des parties des images qu'on va ecarter ou rapprocher
        double taillePartieX   = (double)image->width() / (double)abs(nbPixelsEnPlusEnX+1);
        double taillePartieY   = (double)image->height() / (double)abs(nbPixelsEnPlusEnY+1);

        // nouvelle image
        Calque * nouvelleImageX, * nouvelleImage;
        QRgb couleur1, couleur2;

        // on travaille en X d'abord
        if(nbPixelsEnPlusEnX > 0){
            // si on aggrandit en largeur
            // il faut rajouter des colonnes

            nouvelleImageX  = new Calque(largeur, image->height(), QImage::Format_ARGB32);

            int jj = 0;
            for(int j=0; j<image->width(); j++){

                if(jj<nbPixelsEnPlusEnX && j==ceil(taillePartieX*((double)jj+1.0))){

                    // la colonne a rajouter
                    // en fonction de la colonne j-1 et de la colonne j de image
                    for(int i=0; i<image->height(); i++){

                        couleur1    = image->pixel(j-1, i);
                        couleur2    = image->pixel(j, i);
                        couleur1    = qRgba((qRed(couleur1)+qRed(couleur2))/2,
                                        (qGreen(couleur1)+qGreen(couleur2))/2,
                                        (qBlue(couleur1)+qBlue(couleur2))/2,
                                        (qAlpha(couleur1)+qAlpha(couleur2))/2);
                        nouvelleImageX->setPixel(j+jj, i, couleur1);

                    }

                    jj++;
                }

                // les colonnes normales
                for(int i=0; i<image->height(); i++){

                    nouvelleImageX->setPixel(j+jj, i, image->pixel(j, i));

                }
            }

        }else if(nbPixelsEnPlusEnX < 0){
            // si on retrecit en largeur
            // il faut enlever des colonnes

            nouvelleImageX  = new Calque(largeur, image->height(), QImage::Format_ARGB32);

            int jj = 0;
            for(int j=0; j<image->width(); j++){
                if(jj < largeur){
                    // si le suivant nest pas a supprimer
                    if((j+1)!=ceil(taillePartieX*((double)j-(double)jj+1.0))){
                        // on avance normalement
                        for(int i=0; i<image->height(); i++){

                            nouvelleImageX->setPixel(jj, i, image->pixel(j, i));

                        }
                    }else{
                        // sinon, on met 2 colonnes en 1 (j, j+1)->(f(j, j+1))
                        for(int i=0; i<image->height(); i++){
                            couleur1    = image->pixel(j, i);
                            couleur2    = image->pixel(j+1, i);
                            couleur1    = qRgba((qRed(couleur1)+qRed(couleur2))/2,
                                            (qGreen(couleur1)+qGreen(couleur2))/2,
                                            (qBlue(couleur1)+qBlue(couleur2))/2,
                                            (qAlpha(couleur1)+qAlpha(couleur2))/2);
                            nouvelleImageX->setPixel(jj, i, couleur1);
                        }
                        j++;
                    }
                    jj++;
                }
            }

        }else{
            nouvelleImageX  = image;
        }

        // puis en Y
        if(nbPixelsEnPlusEnY > 0){
            // si on aggrandit en hauteur
            // il faut rajouter des lignes

            nouvelleImage   = new Calque(largeur, hauteur, QImage::Format_ARGB32);

            int ii = 0;
            for(int i=0; i<nouvelleImageX->height(); i++){

                if(ii<nbPixelsEnPlusEnY && i==ceil(taillePartieY*((double)ii+1.0))){

                    // la ligne a rajouter
                    // en fonction de la ligne i-1 et de la ligne i de image
                    for(int j=0; j<nouvelleImageX->width(); j++){

                        couleur1    = nouvelleImageX->pixel(j, i-1);
                        couleur2    = nouvelleImageX->pixel(j, i);
                        couleur1    = qRgba((qRed(couleur1)+qRed(couleur2))/2,
                                        (qGreen(couleur1)+qGreen(couleur2))/2,
                                        (qBlue(couleur1)+qBlue(couleur2))/2,
                                        (qAlpha(couleur1)+qAlpha(couleur2))/2);
                        nouvelleImage->setPixel(j, i+ii, couleur1);

                    }

                    ii++;
                }

                // les colonnes normales
                for(int j=0; j<nouvelleImageX->width(); j++){

                    nouvelleImage->setPixel(j, i+ii, nouvelleImageX->pixel(j, i));

                }
            }

        }else if(nbPixelsEnPlusEnY < 0){
            // si on retrecit en hauteur
            // il faut enlever des lignes

            nouvelleImage   = new Calque(largeur, hauteur, QImage::Format_ARGB32);

            int ii = 0;
            for(int i=0; i<nouvelleImageX->height(); i++){

                if(ii<hauteur){
                    // si le suivant nest pas a supprimer
                    if((i+1)!=ceil(taillePartieY*((double)i-(double)ii+1.0))){
                        // on avance normalement
                        for(int j=0; j<nouvelleImageX->width(); j++){

                            nouvelleImage->setPixel(j, ii, nouvelleImageX->pixel(j, i));

                        }
                    }else{
                        // sinon, on met 2 colonnes en 1 (j, j+1)->(f(j, j+1))
                        for(int j=0; j<nouvelleImageX->width(); j++){
                            couleur1    = nouvelleImageX->pixel(j, i);
                            couleur2    = nouvelleImageX->pixel(j, i+1);
                            couleur1    = qRgba((qRed(couleur1)+qRed(couleur2))/2,
                                            (qGreen(couleur1)+qGreen(couleur2))/2,
                                            (qBlue(couleur1)+qBlue(couleur2))/2,
                                            (qAlpha(couleur1)+qAlpha(couleur2))/2);
                            nouvelleImage->setPixel(j, ii, couleur1);
                        }
                        i++;
                    }
                    ii++;
                }
            }

        }else{
            nouvelleImage   = nouvelleImageX;
        }

        // la nouvelle image se trouve dans nouvelleImage
        fenetre->changerCalqueCourant(nouvelleImage);

        fenetre->updateCalqueCourant();
    }

    delete monDialogue;
}

void ActionImage::selectionRectangulaire(){
    relacheOutils();

    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    this->fenetre->getMonUi()->VueImage->setCursor(Qt::CrossCursor);
    this->mainWindow->getUi()->actionSelection_Rectangulaire->setChecked(true);

    fenetre->getMonEcouteur()->setMode(EcouteurSourisGraphicsView::SELRECT);
}

void ActionImage::pipette(){
    relacheOutils();

    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    QPixmap pixmap(":new/Images/pipette.png");
    pixmap = pixmap.scaled(32, 32);
    QCursor curseur(pixmap, 6, 22);
    this->fenetre->getMonUi()->VueImage->setCursor(curseur);
    this->mainWindow->getUi()->actionPipette->setChecked(true);

    fenetre->getMonEcouteur()->setMode(EcouteurSourisGraphicsView::PIPETTE);
}

void ActionImage::crayon(){
    relacheOutils();

    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    QPixmap pixmap(":new/Images/crayon.png");
    pixmap = pixmap.scaled(32, 32);
    QCursor curseur(pixmap, 7, 29);
    this->fenetre->getMonUi()->VueImage->setCursor(curseur);
    this->mainWindow->getUi()->actionCrayon->setChecked(true);

    //on met a jour l'historique
    Calque *copie = fenetre->getCalqueCourant()->copie();
    ElementHistorique* eh = new ElementHistorique(QString("Dessin"), copie);
    fenetre->historique.ajouter(eh);

    fenetre->getMonEcouteur()->setMode(EcouteurSourisGraphicsView::CRAYON);
}

void ActionImage::deplacement(){
    relacheOutils();

    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    this->fenetre->getMonUi()->VueImage->setCursor(Qt::SizeAllCursor);
    this->mainWindow->getUi()->actionDeplacement->setChecked(true);

    fenetre->getMonEcouteur()->setMode(EcouteurSourisGraphicsView::DEPLACEMENT);
}

void ActionImage::accentuationContours(){
    int seuilInf= 50;

    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    Calque * imageATraiter  = fenetre->getCalqueCourant();

    // on garde en memoire l'ancienne image
    Calque *memoire = imageATraiter->copie();
    ElementHistorique* eh = new ElementHistorique(QString("accentuation Contour"), memoire);
    fenetre->historique.ajouter(eh);

    QImage * sobel  = new QImage(imageATraiter->copy());
    QImage * copie  = new QImage(imageATraiter->copy());
    ActionFiltre::contoursSobel(sobel);

    QRgb couleur;
    int valeurR;
    int valeurV;
    int valeurB;

    // on passe sur tous les pixels de copie
    for(int i=1; i<sobel->height()-1; i++){
        for(int j=1; j<sobel->width()-1; j++){
            // s'il y a un contour assez marque
            if(qRed(sobel->pixel(j, i)) > seuilInf){

                // on applique le rehaussement
                valeurR = 0;
                valeurV = 0;
                valeurB = 0;

                couleur = imageATraiter->pixel(j, i-1);
                valeurR -= qRed(couleur);
                valeurV -= qGreen(couleur);
                valeurB -= qBlue(couleur);
                couleur = imageATraiter->pixel(j-1, i);
                valeurR -= qRed(couleur);
                valeurV -= qGreen(couleur);
                valeurB -= qBlue(couleur);
                couleur = imageATraiter->pixel(j+1, i);
                valeurR -= qRed(couleur);
                valeurV -= qGreen(couleur);
                valeurB -= qBlue(couleur);
                couleur = imageATraiter->pixel(j, i+1);
                valeurR -= qRed(couleur);
                valeurV -= qGreen(couleur);
                valeurB -= qBlue(couleur);

                couleur = imageATraiter->pixel(j, i);
                valeurR += qRed(couleur)     * 5;
                valeurV += qGreen(couleur)   * 5;
                valeurB += qBlue(couleur)    * 5;

                valeurR    = std::min(255, std::max(0, valeurR));
                valeurV     = std::min(255, std::max(0, valeurV));
                valeurB     = std::min(255, std::max(0, valeurB));

                copie->setPixel(j, i, qRgba(valeurR, valeurV, valeurB, qAlpha(couleur)));

            }

        }
    }

    for(int i=1; i<sobel->height()-1; i++){
        for(int j=1; j<sobel->width()-1; j++){
            imageATraiter->setPixel(j, i, copie->pixel(j, i));
        }
    }

    fenetre->a_ete_modifie=true;
    fenetre->updateCalqueCourant();

    delete sobel;
    delete copie;
}

void ActionImage::seamCarving(){
    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    Calque * image  = fenetre->getCalqueCourant();

    // on garde en memoire l'ancienne image
    Calque* memoire = image->copie();
    ElementHistorique* eh = new ElementHistorique(QString("Seam Carving"), memoire);
    fenetre->historique.ajouter(eh);

    MonDialogueRedimensionnement * monDialogue = new MonDialogueRedimensionnement(this);
    int acceptation = monDialogue->exec();

    if(acceptation == QDialog::Accepted){

        // on calcule les nouvelles dimensions
        int largeur = (image->width()*monDialogue->getPourcentageLargeur()) /100;
        int hauteur = (image->height()*monDialogue->getPourcentageHauteur()) /100;

        // la difference de taille
        int nbPixelsEnPlusEnX   = largeur - image->width();
        int nbPixelsEnPlusEnY   = hauteur - image->height();

        // on applique sobel sur une copie de l'image
        QImage * copie  = new QImage(image->copy());
        ActionFiltre::contoursSobel(copie);
        // on calcule les chemins d'energie minimale
        for(int i=0; i<abs(nbPixelsEnPlusEnY); i++){
            Matrices::cheminHorizontalDEnergieMinimale(copie);
            // puis on le traite
            this->annexeSeamCarving(&image, &copie, nbPixelsEnPlusEnY>0, true);
        }

        copie  = new QImage(image->copy());
        ActionFiltre::contoursSobel(copie);
        for(int j=0; j<abs(nbPixelsEnPlusEnX); j++){
            Matrices::cheminVerticalDEnergieMinimale(copie);
            this->annexeSeamCarving(&image, &copie, nbPixelsEnPlusEnX>0, false);
        }

        fenetre->changerCalqueCourant(image);
        fenetre->updateCalqueCourant();

    }

    delete monDialogue;
}

void ActionImage::annexeSeamCarving(Calque ** imageDepart, QImage ** informations, bool augmentation, bool changementVertical){
    Calque * nouvelleImage;
    QImage * nouvellesInformations;
    QRgb couleur;

    Calque * calqueTmp = *imageDepart;
    QImage * qimageTmp = *informations;

    // puis on execute le changement
    if(augmentation){
        if(changementVertical){
            int nouvelleHauteur = calqueTmp->height() +1;
            nouvelleImage = new Calque(calqueTmp->width(), nouvelleHauteur, calqueTmp->format());
            nouvellesInformations = new QImage(calqueTmp->width(), nouvelleHauteur, calqueTmp->format());

            QRgb couleur, couleur2;

            // parcours en largeur
            for(int j=0; j<calqueTmp->width(); j++){
                int i=0;
                while(qRed(couleur=qimageTmp->pixel(j, i))!=255 || qGreen(couleur)!=0){
                    nouvellesInformations->setPixel(j, i, couleur);
                    couleur = calqueTmp->pixel(j, i);
                    nouvelleImage->setPixel(j, i, couleur);
                    i++;
                }

                couleur     = calqueTmp->pixel(j, i);
                if(i == 0){
                    couleur2    = calqueTmp->pixel(j, i+1);
                }else{
                    couleur2    = calqueTmp->pixel(j, i-1);
                }

                nouvellesInformations->setPixel(j, i, qRgb(255,255,255));
                nouvelleImage->setPixel(j, i, qRgba(
                                            (qRed(couleur) + qRed(couleur2))/2,
                                            (qGreen(couleur) + qGreen(couleur2))/2,
                                            (qBlue(couleur) + qBlue(couleur2))/2,
                                            (qAlpha(couleur) + qAlpha(couleur2))/2
                                            ));

                for(int ii=i; ii<calqueTmp->height(); ii++){
                    couleur = qimageTmp->pixel(j, ii);
                    nouvellesInformations->setPixel(j, ii+1, couleur);
                    couleur = calqueTmp->pixel(j, ii);
                    nouvelleImage->setPixel(j, ii+1, couleur);
                }
            }
        }else{
            int nouvelleLargeur = calqueTmp->width() +1;
            nouvelleImage = new Calque(nouvelleLargeur, calqueTmp->height(), calqueTmp->format());
            nouvellesInformations = new QImage(nouvelleLargeur, calqueTmp->height(), calqueTmp->format());

            QRgb couleur, couleur2;

            // parcours en hauteur
            for(int i=0; i<calqueTmp->height(); i++){
                int j=0;
                while(qRed(couleur=qimageTmp->pixel(j, i))!=255 || qGreen(couleur)!=0){
                    nouvellesInformations->setPixel(j, i, couleur);
                    couleur = calqueTmp->pixel(j, i);
                    nouvelleImage->setPixel(j, i, couleur);
                    j++;
                }

                couleur     = calqueTmp->pixel(j, i);
                if(j == 0){
                    couleur2    = calqueTmp->pixel(j+1, i);
                }else{
                    couleur2    = calqueTmp->pixel(j-1, i);
                }

                nouvellesInformations->setPixel(j, i, qRgb(255,255,255));
                nouvelleImage->setPixel(j, i, qRgba(
                                            (qRed(couleur) + qRed(couleur2))/2,
                                            (qGreen(couleur) + qGreen(couleur2))/2,
                                            (qBlue(couleur) + qBlue(couleur2))/2,
                                            (qAlpha(couleur) + qAlpha(couleur2))/2
                                            ));

                for(int jj=j; jj<calqueTmp->width(); jj++){
                    couleur = qimageTmp->pixel(jj, i);
                    nouvellesInformations->setPixel(jj+1, i, couleur);
                    couleur = calqueTmp->pixel(jj, i);
                    nouvelleImage->setPixel(jj+1, i, couleur);
                }
            }
        }
    }else{

        if(changementVertical){
            int nouvelleHauteur = calqueTmp->height() -1;
            nouvelleImage = new Calque(calqueTmp->width(), nouvelleHauteur, calqueTmp->format());
            nouvellesInformations = new QImage(calqueTmp->width(), nouvelleHauteur, calqueTmp->format());

            int ii;
            for(int j=0; j<calqueTmp->width(); j++){
                ii=0;
                for(int i=0; i<calqueTmp->height(); i++){
                    couleur = qimageTmp->pixel(j, i);
                    if(qRed(couleur)==255 && qGreen(couleur)==0){
                        ii++;
                    }else{
                        couleur = calqueTmp->pixel(j, i);
                        nouvelleImage->setPixel(j, i-ii, couleur);
                        couleur = qimageTmp->pixel(j, i);
                        nouvellesInformations->setPixel(j, i-ii, couleur);
                    }
                }
            }
        }else{

            int nouvelleLargeur = calqueTmp->width() -1;
            nouvelleImage = new Calque(nouvelleLargeur, calqueTmp->height(), calqueTmp->format());
            nouvellesInformations = new QImage(nouvelleLargeur, calqueTmp->height(), calqueTmp->format());

            int jj;
            for(int i=0; i<calqueTmp->height(); i++){
                jj=0;
                for(int j=0; j<calqueTmp->width(); j++){
                    couleur = qimageTmp->pixel(j, i);
                    if(qRed(couleur)==255 && qGreen(couleur)==0){
                        jj++;
                    }else{
                        couleur = calqueTmp->pixel(j, i);
                        nouvelleImage->setPixel(j-jj, i, couleur);
                        couleur = qimageTmp->pixel(j, i);
                        nouvellesInformations->setPixel(j-jj, i, couleur);
                    }
                }
            }
        }
    }

    delete *imageDepart;
    *imageDepart    = nouvelleImage;

    delete * informations;
    *informations   = nouvellesInformations;

}

void ActionImage::seamCarvingPrevisualisation(){
    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    Calque * image  = fenetre->getCalqueCourant();

    // on garde en memoire l'ancienne image
    Calque* memoire = image->copie();
    ElementHistorique* eh = new ElementHistorique(QString("Seam Carving previ"), memoire);
    fenetre->historique.ajouter(eh);

    MonDialogueRedimensionnement * monDialogue = new MonDialogueRedimensionnement(this);
    int acceptation = monDialogue->exec();

    if(acceptation == QDialog::Accepted){

        // on calcule les nouvelles dimensions
        int largeur = (image->width()*monDialogue->getPourcentageLargeur()) /100;
        int hauteur = (image->height()*monDialogue->getPourcentageHauteur()) /100;

        // la difference de taille
        int nbPixelsEnPlusEnX   = largeur - image->width();
        int nbPixelsEnPlusEnY   = hauteur - image->height();

        // on applique sobel sur une copie de l'image
        QImage * copie  = new QImage(image->copy());
        ActionFiltre::contoursSobel(copie);
        // on calcule les chemins d'energie minimale
        for(int i=0; i<abs(nbPixelsEnPlusEnY); i++){
            Matrices::cheminHorizontalDEnergieMinimale(copie);
        }

        Calque * imgTmp = new Calque(*copie);
        fenetre->changerCalqueCourant(imgTmp);
        fenetre->updateCalqueCourant();
        // pause
        QMessageBox msgBox;
        msgBox.setText("Seam carving en hauteur");
        msgBox.exec();

        copie  = new QImage(image->copy());
        ActionFiltre::contoursSobel(copie);
        for(int j=0; j<abs(nbPixelsEnPlusEnX); j++){
            Matrices::cheminVerticalDEnergieMinimale(copie);
        }

        imgTmp = new Calque(*copie);
        fenetre->changerCalqueCourant(imgTmp);
        fenetre->updateCalqueCourant();
        msgBox.setText("Seam carving en largeur");
        msgBox.exec();
    }

    delete monDialogue;
}

void ActionImage::ciseaux(){
    relacheOutils();

    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    this->fenetre->getMonUi()->VueImage->setCursor(Qt::CrossCursor);
    this->mainWindow->getUi()->actionCiseaux->setChecked(true);

    fenetre->getMonEcouteur()->setMode(EcouteurSourisGraphicsView::CISEAUX);
}

void ActionImage::autocrop(){
    fenetre = this->getFenetreImageCourante();
    if(fenetre == NULL){ return; }

    Calque * image  = fenetre->getCalqueCourant();

    // on garde en memoire l'ancienne image
    Calque *memoire = fenetre->getCalqueCourant()->copie();
    ElementHistorique* eh = new ElementHistorique(QString("Decoupage Intelligent"), memoire);
    fenetre->historique.ajouter(eh);

    // on fait sobel
    QImage * sobel  = new QImage(image->copy());
    ActionFiltre::contoursSobel(sobel);

    // on calcule le nouveau cadre
    int xDep, yDep, xFin, yFin;

    int indice;
    bool nonTrouve;

    int seuil  = 10;

    // en haut
    indice      = 1;
    nonTrouve   = true;
    while(indice < sobel->height()-1 && nonTrouve){
        // on cherche sur la ligne, s'il y a un pixel d'une intensite minimale
        for(int j=1; j<sobel->width()-1 && nonTrouve; j++){
            nonTrouve   = qRed(sobel->pixel(j, indice)) < seuil;
        }
        indice++;
    }
    yDep = indice;

    // en bas
    indice      = sobel->height()-2;
    nonTrouve   = true;
    while(indice >= yDep && nonTrouve){
        // on cherche sur la ligne, s'il y a un pixel d'une intensite minimale
        for(int j=1; j<sobel->width()-1 && nonTrouve; j++){
            nonTrouve   = qRed(sobel->pixel(j, indice)) < seuil;
        }
        indice--;
    }
    yFin = indice;

    // a gauche
    indice      = 1;
    nonTrouve   = true;
    while(indice < sobel->width()-1 && nonTrouve){
        // on cherche sur la ligne, s'il y a un pixel d'une intensite minimale
        for(int j=1; j<sobel->height()-1 && nonTrouve; j++){
            nonTrouve   = qRed(sobel->pixel(indice, j)) < seuil;
        }
        indice++;
    }
    xDep = indice;

    // a droite
    indice      = sobel->width()-2;
    nonTrouve   = true;
    while(indice >= xDep && nonTrouve){
        // on cherche sur la ligne, s'il y a un pixel d'une intensite minimale
        for(int j=1; j<sobel->height()-1 && nonTrouve; j++){
            nonTrouve   = qRed(sobel->pixel(indice, j)) < seuil;
        }
        indice--;
    }
    xFin = indice;

    QImage *copie = new QImage(image->copy(xDep-1, yDep-1, xFin-xDep+2, yFin-yDep+2));

    //on ne garde que le bout croppé
    this->fenetre->changerCalqueCourant(new Calque(*copie, 0, 0));
    this->fenetre->a_ete_modifie = true;
    this->fenetre->updateCalqueCourant();

    delete sobel;
}
